<?php
namespace app\task\queue;
use app\admin\model\BaseSetting;
use app\api\model\User;
use app\api\model\user\BalanceLog as BalanceLogModel;
use app\common\enum\user\balanceLog\Scene as SceneEnum;
use app\common\exception\BaseException;
use app\common\library\wechat\Abonus;
use app\common\library\wechat\WxPay;
use app\common\model\Wxapp as WxappModel;
use org\RabbitMQ;
use utils\Services;

/**
 *  分红队列
 * Class BackAbonusAccounts
 * @package app\task\queue
 */
class BackAbonusAccounts
{


    public function getBackAbonus(){
        $rmq = new RabbitMQ;
        $processMessage = function ($envelope, $queue) {
            $msg = $envelope->getBody();
            $params= json_decode($msg,true);
            $this-> getMultipleBackAbonus($params['orderId'],$params['periodsNum'],$params['trade']);
        };
        $rmq->run($processMessage, 'userListData','userListDataLog','userListDataLog');
    }

    private function getMultipleBackAbonus($orderId,$periodsNum,$trade){
        $order=$this->getOrderInfo($orderId);//获取订单信息
        $setting=$this->getSetting($order['wxapp_id']);//获取本次分红设置
        $userMoney=$this->getUserMoney($order,$setting['realmoney']);//计算用户总的分红金额
        $proportion=($userMoney/$order['pay_price'])*100;//用户分红比例
        $userList=collection(db('divide_receive')
            ->where(['wxapp_id'=>$order['wxapp_id'],'pay_type'=>0,'status'=>1,'periods_num'=>$periodsNum,'user_id'=>['neq',0]])
            ->field('order_no,trade,wxapp_id,description,proportion,periods_num,user_id,account,amount,top_limit,SUM(amount) as devide_num')
            ->group('trade')
            ->select())->toArray();

        //调用分账接口
        $Abonus=new Abonus($order['wxapp_id']);
        if(count($userList)==0){
            //当小程序商户第一次参加的时候，没有数据，第一条数据直接写入
            $res=$this->getOneUserBackAbonus($order['wxapp_id'],$order['transaction_id'],$order['pay_price'],$userMoney);
            if($res==true){
                //将出账方写入数据库
                $this->setUserBackAccounts($trade,$userMoney,$proportion,$order['pay_price']);
                //将店员的分红写入数据库
                $this->setStoreStaffAccounts($order,$setting,$trade,$userMoney,$proportion);
                //调用分账接口
                $Abonus->getDivideList($order);
            }else{
                throw new BaseException(['msg' => '退款失败']);
            }
        }else{
            $userListData=[];
            //将最新出资方退款
            $res=$this->getOneUserBackAbonus($order['wxapp_id'],$order['transaction_id'],$order['pay_price'],$userMoney);

            if($res==true){
                //统计实际参与分账人数,参与分账的用户分账的金额已返完的不参与分账
                foreach ($userList as $key=>$item){
                    if($item['devide_num']<$item['top_limit']){
                        $userListData[$key]['pay_type']       =0;//是否参与分账，0，参与，1.不参与
                        $userListData[$key]['trade']          =$item['trade'] ;
                        $userListData[$key]['order_no']       =$item['order_no'] ;
                        $userListData[$key]['wxapp_id']       =$item['wxapp_id'] ;
                        $userListData[$key]['account']        =$item['open_id'] ;
                        $userListData[$key]['user_id']        =$item['user_id'] ;
                        $userListData[$key]['amount']         =$item['amount'] ;
                        $userListData[$key]['description']    =$item['description'] ;
                        $userListData[$key]['proportion']     =$item['proportion'] ;
                        $userListData[$key]['payment']        =$item['payment'] ;
                        $userListData[$key]['top_limit']      =$item['top_limit'] ;
                        $userListData[$key]['periods_num']    =$item['periods_num'] ;
                        $userListData[$key]['transaction_id'] =$item['transaction_id'] ;
                        $userListData[$key]['status']         =1 ;
                        $userListData[$key]['create_time']    =time() ;
                        $userListData[$key]['update_time']    =time() ;
                        $res=$this->getOneUserBackAbonus($item['wxapp_id'],$item['transaction_id'],$item['payment'],$userMoney);
                        if($res){
                            db('divide_receive')->insert($userListData);
                        }
                    }else{
                        $userListData[$key]['pay_type']       =1;//是否参与分账，0，参与，1.不参与
                        //订单实际分得金额
                        $userRealMoney=$item['top_limit']-$item['devide_num'];
                        //将用户分到的分红，减去能够返还的金额，剩余金额转化为零钱
                        $UserBalance=$userMoney-$userRealMoney;
                        //将转化的积分存入相对应的用户账户
                        $this->getUserBlance($item['user_id'],$UserBalance);
                        $userListData[$key]['trade']          =$item['trade'] ;
                        $userListData[$key]['order_no']       =$item['order_no'] ;
                        $userListData[$key]['wxapp_id']       =$item['wxapp_id'] ;
                        $userListData[$key]['account']        =$item['open_id'] ;
                        $userListData[$key]['user_id']        =$item['user_id'] ;
                        $userListData[$key]['amount']         =$userRealMoney ;
                        $userListData[$key]['description']    =$item['description'] ;
                        $userListData[$key]['proportion']     =$item['proportion'] ;
                        $userListData[$key]['payment']        =$item['payment'] ;
                        $userListData[$key]['top_limit']      =$item['top_limit'] ;
                        $userListData[$key]['periods_num']    =$item['periods_num'] ;
                        $userListData[$key]['transaction_id'] =$item['transaction_id'] ;
                        $userListData[$key]['status']         =1 ;
                        $userListData[$key]['create_time']    =time() ;
                        $userListData[$key]['update_time']    =time() ;
                        //退还之前的定的分红额
                        $res=$this->getOneUserBackAbonus($item['wxapp_id'],$item['transaction_id'],$item['payment'], $userRealMoney);
                        if($res){
                            db('divide_receive')->insert($userListData);
                        }
                    }
                }
                //将出账方写入数据库
                if ($this->setUserBackAccounts($order,$trade,$periodsNum,$userMoney,$proportion)){
                    //将店员的分红写入数据库
                    $this->setStoreStaffAccounts($order,$setting,$trade,$userMoney,$proportion);
                    //调用分账接口
                    $Abonus->getDivideList($order);
                }
            }else{
                throw new BaseException(['msg' => '退款失败']);
            }
        }
    }
    /**
     * 将退款用户写入数据库
     * @param $trade
     * @param $userMoney
     * @param $proportion
     * @param $totalMoney
     */
    private function setUserBackAccounts($order,$trade,$periodsNum,$userMoney,$proportion){

        $setting=$this->getSetting($order);

        $userListData['order_no']        = $order['order_no'] ;//订单号
        $userListData['payment']         = $order['pay_price'] ;//订单支付金额
        $userListData['transaction_id']  = $order['transaction_id'] ;//订单号
        $userListData['trade']           = $trade;//分账单号，小程序号+期号+时间;
        $userListData['pay_type']        = 0;//是否参与分账，0，参与，1.不参与
        $userListData['description']     = '退款给用户' ;
        $userListData['periods_num']     = $periodsNum ;//活动期号
        $userListData['proportion']      = $proportion ;//分账比例
        $userListData['user_id']         = $order['user_id'] ;
        $userListData['account']         = $this->getUserOpenId($order['user_id'],$order['wxapp_id']) ;
        $userListData['top_limit']       = (($setting['upline']/100)*($order['pay_price']))*100;
        $userListData['amount']          = $userMoney;
        $userListData['status']          = 1;
        $userListData['wxapp_id']        = $order['wxapp_id'];//微信小程序id
        $userListData['create_time']     = time();//写入时间（支付时间）
        $userListData['update_time']     = time();//写入时间（支付时间）
        return db('divide_receive')->insert($userListData);
    }
    /**
     *  参与分红的商户店员写入数据库
     * @param $trade string  分红期号
     * @param $money int  跟随用户分红的时候的分红金额
     * @param $proportion int 跟随用户分红的时候的分红比例
     * @param $totalMoney int 总支付金额
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function setStoreStaffAccounts($order,$setting,$trade,$money,$proportion){

        $staffUserList=db('store_shop_clerk')->where(array('wxapp_id'=>$order['wxapp_id'],'type'=>1,'shop_id'=>$order['extract_shop_id']))->field('clerk_id,open_id,abonus')->select();
        if($staffUserList->isEmpty()){
            return false;
        }else{
            $staffUserDataArray=[];
            foreach ($staffUserList as $key=>$value){
                if($value['pay_type']==0){
                    $staffUserDataArray['amount']        =$money;
                    $staffUserDataArray['proportion']    =$proportion;//分账比例（百分比）
                }else{
                    $staffUserDataArray['amount']        =($value['abonus']/100)*($order['pay_price']*(1-($setting['term']/100)));
                    $staffUserDataArray['proportion']    = $value['abonus'];;//分账比例（百分比）
                }
                $staffUserDataArray['trade']         =$trade;//代言人id
                $staffUserDataArray['order_no']      =$order['order_no'];//代言人id
                $staffUserDataArray['wxapp_id']      =$order['wxapp_id'];//代言人id
                $staffUserDataArray['clerk_id']      =$value['clerk_id'];//代言人id
                $staffUserDataArray['account']       =$value['open_id'];
                $staffUserDataArray['description']   ='分账给商户代言人';
                $staffUserDataArray['payment']       =$order['pay_price'];
                $staffUserDataArray['periods_num']   =$setting['periods_num'];
                $staffUserDataArray['transaction_id']=$order['transaction_id'];//代言人id
                $staffUserDataArray['status']        =0;
                $staffUserDataArray['create_time']   =time();
                db('divide_store_clerk')->insert($staffUserDataArray);
            }

        }
    }

    /**
     * 调用退款接口
     * @param $transaction_id
     * @param $payment
     * @param $userMoney
     * @return bool
     * @throws BaseException
     * @throws \think\Exception
     * @throws \think\exception\DbException
     */
    private function getOneUserBackAbonus($wxappId,$transaction_id,$payment,$userMoney){

        $wxConfig = WxappModel::getWxappRedis($wxappId);

        //获取证书
        if (empty($wxConfig['mchid']) || empty($wxConfig['app_id'])) {
            throw new BaseException(['msg' => '请先到后台小程序设置填写微信支付相关内容']);
        }
        $WxPay = new WxPay($wxConfig);

        return $WxPay->refund($transaction_id,$payment,$userMoney); //用户分红回退
    }

    /**
     *  参与分红代言人可以分到的钱
     * @param $totalMoney
     * @return float|int
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function getUserMoney($order,$setting){


        $totalUserMoney=$order['pay_price']*(1-($setting['realmoney']/100)-0.01);//用户总的分账金额
        //参与分红的代言人
        $staff=$this->getStoreStaffDivideCount($order);
        //如果代言人参与分红
        if($staff!==false){
            $userCount=intval($this->getUserAccounts($order['wxapp_id'],$setting['periods_num']))+1+$staff;//分账用户总数,加入本次出账方一人和商铺代言人
        }else{
            $userCount=intval($this->getUserAccounts($order['wxapp_id'],$setting['periods_num']))+1;//分账用户总数,加入本次的出账方一人
        }
        $userMoney=$totalUserMoney/$userCount;//单个用户分账的金额
        return $userMoney;//单位分
    }
    /***
     *  统计参与分账的代言人
     * @return bool|int|string
     * @throws \think\Exception
     */
    private function getStoreStaffDivideCount($order){
        return db('store_shop_clerk')->where(array('wxapp_id'=>$order['wxapp_id'],'type'=>1,'shop_id'=>$order['extract_shop_id']))->count();
    }
    /**
     *  统计参与分红的用户
     * @return int
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function getUserAccounts($wxappId,$periodsNum){

        $userList=collection(db('divide_receive')
            ->where(['wxapp_id'=>$wxappId,'pay_type'=>0,'status'=>1,'periods_num'=>$periodsNum,'user_id'=>['neq',0]])
            ->field('order_no,trade,wxapp_id,description,proportion,periods_num,user_id,account,amount,top_limit,SUM(amount) as devide_num')
            ->group('trade')
            ->select())->toArray();
        $userCount=0;//参与分账的人数
        //统计实际参与分账人数,参与分账的用户分账的金额已返完的不参与分账
        foreach ($userList as $item){
            if($item['devide_num']<$item['top_limit']){
                $userCount++;
            }
        }
        return $userCount;

    }

    /**
     * 获取用户的open_id
     * @param $userId int 用户id
     * @param $wxappId int 微信id
     * @return bool|float|mixed|string|null
     */

    private function getUserOpenId($userId,$wxappId){
        return db('user')->where(['user_id'=>$userId,'wxapp_id'=>$wxappId])->value('open_id');
    }
    private function getOrderInfo($orderId){
       return  db('order')->where('order_id',$orderId)->find();
   }

    private function getSetting($order){
       return  db('wxapp_setting')->where('wxapp_id',$order['wxapp_id'])->find();
    }

    /**
     * 将用户多余的积分给用户加上
     * @param $userId  int 用户id
     * @param $chage  int 零钱
     * @param $trade  int 分红单号
     */
    private function getUserBlance($userId,$chage){
        $userModel=new User();
        $userModel->where('user_id',$userId)->setDec('balance',$chage);
    }

}